﻿app.controller("panel", [
    "$rootScope", "$scope", "$timeout", "$q", "$http", "signalrHub", "systrayService", "panelService",
    function ($rootScope, $scope, $timeout, $q, $http, signalrHub, systrayService, panelService) {
        $scope.panelToLoad = null;
        $scope.debug = false;
        $scope.includes = [];
        $scope.brokenWidgets = [];

        $scope.init = function (panelToLoad, debug) {
            systrayService.enable();

            $scope.panelToLoad = panelToLoad;
            $scope.debug = debug;

            var options = {
                float: true,
                cell_height: 30
            };
            $(".grid-stack").gridstack(options);
        };

        $scope.startSignalr = function() {
            var hub = signalrHub.init("dashboard");
            hub.on("widgetUpdateCommand", function(update) {
                console.log("widgetUpdateCommand received!");

                if (update.TargetPanelInstanceId) {
                    if (update.TargetPanelInstanceId !== $scope.panelIdentity.panelInstanceId) {
                        console.log("ignoring widget update, not for this panel instance!");
                        return;
                    }
                }

                // TODO: Use Directive
                var payload = update.Payload.replace(/'/g, "\\'").replace(/(\r\n|\n|\r)/gm, "");
                var widgetScript = "if (window._" + update.TargetWidgetId + " && window._" + update.TargetWidgetId + ".update) { " +
                    "console.log('widget updated!');" +
                    "_" + update.TargetWidgetId + ".update('" + payload + "'); }";
                console.log(widgetScript);

                try {
                    eval(widgetScript);

                    // was broken, now fixed...remove from list of bust widgets
                    if (update.TargetWidgetId in $scope.brokenWidgets) {
                        delete $scope.brokenWidgets[update.TargetWidgetId];
                        $rootScope.$broadcast("widget.update-fixed", $scope.brokenWidgets);
                    }

                } catch (error) {
                    console.log('error updating widget \'' + update.TargetWidgetId + '\': ' + error);

                    if (!(update.TargetWidgetId in $scope.brokenWidgets)) {
                        $scope.brokenWidgets[update.TargetWidgetId] = {
                            widget: update.TargetWidgetId,
                            error: error
                        };
                        $rootScope.$broadcast("widget.update-failed", $scope.brokenWidgets);
                    }
                }
            });

            return hub.start();
        };

        $scope.loadPanel = function () {
            console.log("start:loading panel...");
            return panelService.load($scope.panelToLoad);
        }

        $scope.loadStylesheets = function (panel) {
            console.log("start:loading stylesheets ("+ panel.styleSheets.length + ")...");

            var stylesheets = [];

            panel.styleSheets.forEach(function (css) {
                if (css.name in $scope.includes) {
                    console.log(css.name + " already loaded!");
                } else {
                    $scope.includes[css.name] = css.value;
                    stylesheets.push(css.value);
                }
            });

            if (stylesheets.length === 0) {
                return panel;
            }

            console.log("need to load "+ stylesheets.length + " stylesheets...");
            console.log(stylesheets);

            var deferred = $q.defer();
            LazyLoad.css(stylesheets, function () {
                console.log("stylesheets loaded!");
                deferred.resolve(panel);
            });

            console.log("LazyLoad exited!");
            return deferred.promise;
        };

        $scope.addWidgetsToGrid = function (panel) {
            console.log("start:adding widgets (" + panel.widgets.length + ")...");

            panel.widgets.forEach(function(widget) {
                var grid = $(".grid-stack").data("gridstack");
                grid.add_widget($('<div><div id="w_' + widget.id + '" class="grid-stack-item-content">' + widget.markup + '</div></div>'),
                                widget.column, widget.row, widget.width, widget.height);
            });

            return panel;
        };

        $scope.loadScripts = function (panel) {
            console.log("start:loading scripts (" + panel.scripts.length + ")...");

            var scripts = [];

            panel.scripts.forEach(function (script) {
                if (script.name in $scope.includes) {
                    console.log(script.name + " already loaded!");
                } else {
                    $scope.includes[script.name] = script.value;
                    scripts.push(script.value);
                }
            });

            if (scripts.length === 0) {
                return panel;
            }

            console.log("need to load " + scripts.length + " scripts...");
            console.log(scripts);

            var deferred = $q.defer();
            LazyLoad.js(scripts, function() {
                console.log("scripts loaded!");
                deferred.resolve(panel);
            });

            console.log("LazyLoad exited!");
            return deferred.promise;
        };

        $scope.finalisePanelLoad = function(panel) {
            console.log("finalising panel load...");

            $scope.panelIdentity = {
                panelId: panel.id.toString(),
                panelName: panel.name,
                panelInstanceId: panel.instanceId.toString(),
                panelVersion: panel.version.toString()
            };

            return $q(function(resolve) {
                $http.post("/dashboard/panel/loaded", $scope.panelIdentity)
                    .then(function (httpResponse) {
                        resolve(panel);
                    });
            });
        };

        $scope.panelLoaded = function(panel) {
            console.log("panel '"+ panel.name +"' loaded!");
        }

        $scope.start = function () {
            console.log("start() begin...");

            $scope.startSignalr()
                .then($scope.loadPanel)
                .then(function(httpResponse) {
                    return $scope.loadStylesheets(httpResponse.data);
                })
                .then($scope.addWidgetsToGrid)
                .then(function(panel) {
                    return $scope.loadScripts(panel);
                })
                .then($scope.finalisePanelLoad)
                .then($scope.panelLoaded);

            console.log("start() exit");
        };

        $timeout(function() {
            $scope.start();
        }, 10);
    }
]);